package parser

import (
	"bytes"
	"dc/context"
	"dc/visitor"
	"github.com/gammazero/deque"
	"golang.org/x/net/html"
)

type Parser struct {
	root *html.Node
}

func New(source []byte) (*Parser, error) {
	r, err := html.Parse(bytes.NewReader(source))
	if err != nil {
		return nil, err
	}
	return &Parser{
		root: r,
	}, nil
}

func (p *Parser) String() string {
	var b bytes.Buffer
	_ = html.Render(&b, p.root)
	return b.String()
}

func (p *Parser) Parse(data map[string]interface{}) error {
	ctx := context.New(data)

	q := deque.Deque[*html.Node]{}
	q.PushBack(p.root)
	for q.Len() > 0 {
		n := q.PopFront()
		if v, ok := visitor.GetVisitor(n.DataAtom); ok {
			err := v.Visit(ctx, n)
			if err != nil {
				return err
			}
			continue
		}
		err := visitor.DefaultVisitor.Visit(ctx, n)
		if err != nil {
			return err
		}
		if n.FirstChild != nil {
			q.PushBack(n.FirstChild)
		}
		if n.NextSibling != nil {
			q.PushBack(n.NextSibling)
		}
	}
	return nil
}
